import { locations } from "../../../../gpu/locations";
export const PunctusLight_def = /*wgsl*/ `
#if ~{def.punctualLight}
@group(${locations.punctualLight[0]}) @binding(${locations.punctualLight[1]}) var<uniform> punctusLight:PunctusLight;
@group(${locations.punctualCount[0]}) @binding(${locations.punctualCount[1]}) var<uniform> punctualCount:i32;
//精准光源的光线
struct LightRay {
    color:vec3<f32>,//0
    t:f32,//type //3
    position:vec3<f32>,//4
    intensity:f32,//7
    at:vec3<f32>,//8
    range:f32,//11
    e1:f32,//12   //面光源中e1,e2对应width,height  聚光灯中对应innerCos outerCos
    e2:f32,//13
    e3:f32,//14
    e4:f32,//15
}
//精准光源
struct PunctusLight{
    lights:array<LightRay, 10>,
}
//计算精准光源光照结果
fn cal_punctusLight(input:Input)->vec3<f32>{
    var Lo:vec3<f32>=vec3(0.0);
    for(var i: i32 = 0; i < punctualCount; i++) {
        var l=punctusLight.lights[i];
        var direction:vec3<f32>=vec3(0.0);
        var distance:f32=0.0;
        if(l.t== 0.0) {
            break;
        }
        if(l.t==4.0){ //面光源计算是否在范围内
            var flag:bool=input.fragPosition[0]>=l.position[0]-l.e1/2&&input.fragPosition[0]<=l.position[0]+l.e1/2&&input.fragPosition[1]>=l.position[1]-l.e2/2&&input.fragPosition[1]<=l.position[1]+l.e2/2;
            if(flag == false){
            continue;
            }
        }
        if(l.t==3.0 ||l.t==4.0){
            direction =l.position-l.at;
        }else{
            direction =l.position-input.fragPosition;
        }
        distance = length(direction);//光源距离

        var diffuse: f32 =max(dot(normalize(direction), normal), 0.0);
        var decay:f32=1.0;//计算衰减
        if(l.t==1.0){
            decay*=attenuation(distance, l.range);
        }else if(l.t==2.0){
            decay*=attenuation(distance, l.range);
            var l1:vec3<f32> = normalize(l.position - l.at);//光源向量
            var angleCos = dot(l1,normalize(direction));
            decay*=attenuationSpot(l.e1,l.e2,angleCos);
        }
        var view:vec3<f32>= normalize(camera.position - input.fragPosition);
        var halfDirection:vec3<f32> = normalize(view + normalize(direction));
        var specularWeighting:f32 = clamp(dot(halfDirection, normal),0.0,1.0);
        specularWeighting=pow(specularWeighting, material.shininess);
        Lo=Lo+material.color.xyz*l.color*l.intensity*diffuse*decay+material.specular*l.color*l.intensity*specularWeighting*decay;
    }
    return Lo;
}
//计算光照衰减
fn attenuation(distance:f32,range:f32)->f32{
    if (range == 0.0)
    {
    return 1.0;
    }
    return max(min(1.0 - pow(distance / range, 4.0), 1.0), 0.0) / pow(distance, 2.0);
}
//计算聚光灯角度衰减
fn attenuationSpot(innerCos:f32, outerCos:f32, angleCos:f32)->f32{
    if(angleCos>innerCos){
    return 1-smoothstep(innerCos,innerCos+0.001,angleCos);
    }
    return 1-smoothstep( innerCos,outerCos, angleCos);
}
#endif`